﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using DevExpress.LookAndFeel;
using DevExpress.Utils;
using DevExpress.XtraEditors;
using RestaurantCommon;

namespace Restaurant.Controls
{
    public partial class ProductsUserControl : UserControl
    {
        private Controller _controller;
        private long _parentNodeId;
        private long? _backNodeId;
        private long _rootNodeId;
        private bool _readOnly;
        private ArvoreProdutoDataSet _productsTreeData;

        internal class ButtonProperties
        {
            private readonly long? _backNodeId;
            private readonly long _parentNodeId;
            private readonly long _nodeId;
            private readonly string _productReference;

            public ButtonProperties(long? backNodeId, long parentNodeId, long nodeId, string productReference)
            {
                _backNodeId = backNodeId;
                _parentNodeId = parentNodeId;
                _nodeId = nodeId;
                _productReference = productReference;
            }

            public long? BackNodeId { get { return _backNodeId; } }
            public long ParentNodeId { get { return _parentNodeId; } }
            public long NodeId { get { return _nodeId; } }
            public string ProductReference { get { return _productReference; } }
        }

        #region Properties

        public Controller Controller
        {
            set
            {
                _controller = value;
                _controller.ProductSynchronized += delegate { RefreshProducts(); };
                _controller.ProductTreeSaved += delegate { RefreshProducts(); };
                _productsTreeData = _controller.ProductsTree();
                _rootNodeId = GetRootProductTree();
                _parentNodeId = _rootNodeId;
                _backNodeId = null;
            }
        }

        public bool ReadOnly
        {
            set { _readOnly = value; }
        }

        
        #endregion

        public ProductsUserControl()
        {
            InitializeComponent();            
        }

        public event EventHandler<ProductEventArgs> ProductSelected;

        public void Populate()
        {
            ShowChildNodes();
        }

        #region Private Methods

        private long GetRootProductTree()
        {
            foreach (ArvoreProdutoDataSet.ArvoreProdutoRow productTree in _productsTreeData.ArvoreProduto)
                if (productTree.IsIdPaiNull())
                    return productTree.Id;
            return -1;
        }

        private long? GetParentProductTree(long nodeId)
        {
            if(nodeId == _rootNodeId)
                return null;
            foreach (var productTree in _productsTreeData.ArvoreProduto)
                if (productTree.Id == nodeId)
                    return productTree.IdPai;
            return null;
        }

        private void RefreshProducts()
        {
            ArvoreProdutoDataSet productsTreeData = _controller.ProductsTree();
            if(productsTreeData.ArvoreProduto.FindById(_parentNodeId) == null)
            {
                _parentNodeId = _rootNodeId;
                _backNodeId = null;
            }
            _productsTreeData = productsTreeData;
            ShowChildNodes();
        }

        private void RemoveButtons()
        {
            var count = Controls.Count;
            for (var controlIndex = 0; controlIndex < count; controlIndex++)
            {
                var control = Controls[0];
                Controls.Remove(control);
                control.Dispose();
            }
        }

        private SimpleButton AddButton(string text, Color topColor, Color bottomColor)
        {
            var button = new SimpleButton
            {
                Width = 100,
                Height = 70,
                //Font = defaultButton.Font,
                Text = text,
                ForeColor = Color.White
            };
            button.Appearance.BackColor = topColor;
            button.Appearance.BackColor2 = bottomColor;
            button.Appearance.GradientMode = LinearGradientMode.Vertical;
            button.Appearance.TextOptions.WordWrap = WordWrap.Wrap;
            button.LookAndFeel.Style = LookAndFeelStyle.Flat;
            button.LookAndFeel.UseDefaultLookAndFeel = false;
            int remainder;
            var quotient = Math.DivRem(Controls.Count, Width / button.Width, out remainder);
            button.Left = remainder * button.Width;
            button.Top = quotient * button.Height;
            Controls.Add(button);
            return button;
        }

        private List<ArvoreProdutoDataSet.ArvoreProdutoRow> GetChildProductTree(long parentNodeId)
        {
            var productsTree = new List<ArvoreProdutoDataSet.ArvoreProdutoRow>();
            foreach(var productTree in _productsTreeData.ArvoreProduto)
                if(!productTree.IsIdPaiNull() && productTree.IdPai == parentNodeId)
                    productsTree.Add(productTree);
            return productsTree;
        }
        
        private void ShowChildNodes()
        {
            RemoveButtons();
            if (_backNodeId != null)
            {
                var backButton = AddButton("Anterior", Color.DimGray, Color.Gainsboro);
                backButton.Tag = new ButtonProperties(_backNodeId, _parentNodeId, 0, null);
                backButton.Click += backButton_Click;
            }
            foreach (var productTree in GetChildProductTree(_parentNodeId))
            {
                var button = productTree.Tipo == (int)ProductTreeType.Folder
                                          ? AddButton(productTree.Nome, Color.Orange, Color.OrangeRed)
                                          : AddButton(productTree.Nome, Color.Azure, Color.MidnightBlue);
                var productReference = productTree.Tipo == (int)ProductTreeType.Folder ? "" : productTree.Produto;
                button.Tag = new ButtonProperties(_backNodeId, _parentNodeId, productTree.Id, productReference);
                button.Click += button_Click;
            }
        }
        
        private void OnProductSelected(string productReference)
        {
            EventHandler<ProductEventArgs> productSelected = ProductSelected;
            if (productSelected != null)
                productSelected(this, new ProductEventArgs(productReference));
        }

        #endregion

        void backButton_Click(object sender, EventArgs e)
        {
            if (_readOnly)
                return;
            var button = (SimpleButton)sender;
            var properties = (ButtonProperties)button.Tag;
            _parentNodeId = properties.BackNodeId.Value;
            _backNodeId = GetParentProductTree(_parentNodeId);
            ShowChildNodes();
        }

        void button_Click(object sender, EventArgs e)
        {
            if (_readOnly)
                return;
            var button = (SimpleButton)sender;
            var properties = (ButtonProperties)button.Tag;
            if (properties.ProductReference != "")
                OnProductSelected(properties.ProductReference);
            else
            {
                _backNodeId = properties.ParentNodeId;
                _parentNodeId = properties.NodeId;
                ShowChildNodes();
            }
                
        }
    }
}
